#pragma once
#include <grpcpp/grpcpp.h>
#include "message.grpc.pb.h"
#include "message.pb.h"
#include <json/json.h>
#include <json/value.h>
#include <json/reader.h>
#include "data.h"
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>
#include "Singleton.h"
#include <unordered_map>


using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;


using message::AddFriendReq;
using message::AddFriendRsp;

using message::ReplyFriendReq;
using message::ReplyFriendRsp;

using message::SendChatMsgReq;
using message::SendChatMsgRsp;

using message::AuthFriendReq;
using message::AuthFriendRsp;

using message::TextChatMsgReq;
using message::TextChatMsgRsp;


//构建一个连接池类
class ChatConPool
{
public:
    ChatConPool(std::size_t poolSize, const std::string &host, const std::string &port)
    :poolSize_(poolSize), host_(host), port_(port), b_stop_(false)
    {
        std::shared_ptr<Channel> chnnel = grpc::CreateChannel(host_+":"+port_, grpc::InsecureChannelCredentials());
        //创建连接，并将连接存入队列中
        for(std::size_t i = 0;i<poolSize_;i++)
        {
            //创建连接
            stubs_.push(message::ChatService::NewStub(chnnel));
        }
    }
    ~ChatConPool()
    {
        stop();
    }

    void stop()
    {
        std::lock_guard<std::mutex> lock(mtx_);
        b_stop_ = true;
        cond_.notify_all();
        while (!stubs_.empty())
        {
            stubs_.pop();
        }
        
    }

    //从连接池中获取一个连接
    std::unique_ptr<message::ChatService::Stub> GetConnection()
    {
        std::unique_lock<std::mutex> lock(mtx_);
        cond_.wait(lock,[this]{
            return !stubs_.empty() || b_stop_;
        });

        if (b_stop_)
        {
            return nullptr;
        }

        //从连接池队列中获取一条连接
        std::unique_ptr<message::ChatService::Stub> conn = std::move(stubs_.front());
        stubs_.pop();
        return conn;
        
    }

    void ReturnConnection(std::unique_ptr<message::ChatService::Stub> conn)
    {
        std::lock_guard<std::mutex> lock(mtx_);
        if (b_stop_)
        {
            return;
        }
        
        stubs_.push(std::move(conn));
        cond_.notify_one();
    }

private:
    std::size_t poolSize_;
    std::string host_;
    std::string port_;
    std::queue<std::unique_ptr<message::ChatService::Stub>> stubs_;


    std::mutex mtx_;
    std::condition_variable cond_;

    bool b_stop_;
};



class ChatGrpcClient:public Singleton<ChatGrpcClient>
{
    friend class Singleton<ChatGrpcClient>;
public:
    ~ChatGrpcClient();

    AddFriendRsp NotifyAddFriend(std::string server_ip, const AddFriendReq &req);

    AuthFriendRsp NotifyAuthFriend(std::string server_ip, const AuthFriendReq &req);

    TextChatMsgRsp NotifyTextChatMsg(std::string server_ip, const SendChatMsgReq &req);

    bool GetBaseInfo(std::string server_ip, std::shared_ptr<UserInfo> userinfo);



private:
    ChatGrpcClient();

private:
    //服务器服务器名字和连接池的映射
    std::unordered_map<std::string, std::unique_ptr<ChatConPool>> _pools;
};